package com.hhd.flow.engine.support;

import com.alibaba.fastjson.JSONObject;
import com.hhd.flow.engine.utils.CommonUtils;
import com.hhd.flow.engine.variable.FlowVariablesContainer;
import com.hhd.flow.entity.FlowProcessInstance;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class FlowFormSupportDelegate {

    @Getter
    static FlowFormSupportDelegate instance;

    @Autowired(required = false)
    List<FlowFormSupport> flowFormSupports;

    public FlowFormSupportDelegate() {
        instance = this;
    }

    public void onCompleteUserTask(JSONObject flowModel, String formType) {
        getFlowFormSupportsByFormType(formType).forEach(f -> f.onCompleteUserTask(flowModel));
    }

    public List<FlowVariablesContainer> loadVariables(String formTypeId, String formId, FlowProcessInstance processInstance) {
        return getFlowFormSupportsByFormType(formTypeId).stream()
                .map(f -> f.loadVariableContainer(formTypeId, formId, processInstance))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    public List<FlowVariablesContainer> loadVariableContainerForDefinition(String formTypeId, String formId, FlowProcessInstance processInstance) {
        return getFlowFormSupportsByFormType(formTypeId).stream()
                .map(f -> f.loadVariableContainerForDefinition(formTypeId, formId, processInstance))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    private List<FlowFormSupport> getFlowFormSupportsByFormType(String formType) {
        if (CommonUtils.isEmpty(flowFormSupports)) return CommonUtils.newList();

        return flowFormSupports.stream().map(f -> {
                    FlowFormSupportAnnotation annotation = CommonUtils.getAnnotation(f, FlowFormSupportAnnotation.class);
                    if (CommonUtils.isEmpty(annotation) || !CommonUtils.isMatch(annotation.formType(), formType)) return null;
                    return new ParsedSupport(annotation.formType(), annotation.order(), f);
                }).filter(Objects::nonNull)
                .sorted(Comparator.comparing(ParsedSupport::getOrder).reversed())
                .map(ParsedSupport::getFlowFormSupport)
                .collect(Collectors.toList());
    }

    public FlowVariablesContainer convertJSONToFormModel(String formTypeId, String formId, FlowProcessInstance processInstance, JSONObject formModel) {
        List<FlowFormSupport> supports = getFlowFormSupportsByFormType(formTypeId);
        if (CommonUtils.isEmpty(supports)) return null;


        FlowVariablesContainer res = null;
        for (FlowFormSupport support : supports) {
            FlowVariablesContainer flowVariablesContainer = support.convertJSONToFormModel(formTypeId, processInstance, formModel);
            if(!CommonUtils.isEmpty(flowVariablesContainer)) res = flowVariablesContainer;
        }
        return res;
    }

    @Getter
    @Setter
    @AllArgsConstructor
    private static class ParsedSupport {
        String formType;
        int order;
        FlowFormSupport flowFormSupport;
    }
}
